//
// Copyright 2018 Google Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// stylelint-disable selector-class-pattern --
// Selector '.mdc-*' should only be used in this project.
// Internal styling for Dialog MDC component.

@use 'sass:map';
@use 'sass:math';
@use '@material/animation/functions' as animation-functions;
@use '@material/button/button-theme';
@use '@material/dom/dom';
@use '@material/elevation/mixins' as elevation-mixins;
@use '@material/feature-targeting/feature-targeting';
@use '@material/rtl/rtl';
@use '@material/shape/mixins' as shape-mixins;
@use '@material/theme/custom-properties';
@use '@material/theme/theme';
@use '@material/theme/theme-color';
@use '@material/touch-target/variables' as touch-target-variables;
@use '@material/typography/typography';
@use './dialog-custom-properties';
@use '@material/icon-button/icon-button-theme';
@use './variables';

@mixin static-styles($query: feature-targeting.all()) {
  $feat-animation: feature-targeting.create-target($query, animation);
  $feat-structure: feature-targeting.create-target($query, structure);

  // prettier-ignore
  @include elevation-mixins.overlay-common($query); // COPYBARA_COMMENT_THIS_LINE

  // postcss-bem-linter: define dialog

  .mdc-dialog,
  .mdc-dialog__scrim {
    @include feature-targeting.targets($feat-structure) {
      position: fixed;
      top: 0;
      left: 0;
      align-items: center;
      justify-content: center;
      box-sizing: border-box;
      width: 100%;
      height: 100%;
    }
  }

  .mdc-dialog {
    // Note: the top padding is only 20px for dialogs without titles; see below for override.
    @include content-padding(20px, 24px, 20px, 24px, $query: $query);
    @include min-width(variables.$min-width, $query: $query);
    @include max-width(variables.$max-width, variables.$margin, $query: $query);
    @include max-height(null, variables.$margin, $query: $query);

    @include feature-targeting.targets($feat-structure) {
      // Use `display: none` instead of `visibility: hidden` to avoid recalculating layout when the dialog is closed.
      display: none;
      $z-index: custom-properties.create(
        dialog-custom-properties.$z-index,
        variables.$z-index
      );
      @include theme.property(z-index, $z-index);
    }

    &.mdc-dialog--fullscreen {
      @include _fullscreen-dialog-size($query: $query);
    }

    &.mdc-dialog__scrim--hidden {
      .mdc-dialog__scrim {
        @include feature-targeting.targets($feat-structure) {
          opacity: 0;
        }
      }
    }
  }

  .mdc-dialog__scrim {
    @include feature-targeting.targets($feat-structure) {
      opacity: 0;
      z-index: -1;
    }
  }

  // This wrapper element is needed to make max-height work in IE 11.
  // See https://github.com/philipwalton/flexbugs/issues/216
  .mdc-dialog__container {
    @include feature-targeting.targets($feat-structure) {
      display: flex;
      flex-direction: row; // IE 11
      align-items: center;
      justify-content: space-around; // Ensure Safari centers the dialog (because it treats the container's width oddly)
      box-sizing: border-box;
      height: 100%;
      opacity: 0;
      // This element is necessary for IE 11 and needs to have `height: 100%`.
      // Let clicks on element fall through to scrim element underneath.
      pointer-events: none;
    }
  }

  .mdc-dialog__surface {
    @include elevation-mixins.overlay-surface-position($query: $query);
    @include elevation-mixins.overlay-dimensions(100%, $query: $query);

    @include feature-targeting.targets($feat-structure) {
      display: flex;
      flex-direction: column;
      flex-grow: 0; // IE 11
      flex-shrink: 0; // IE 11
      box-sizing: border-box;
      max-width: 100%; // IE 11
      max-height: 100%; // IE 11
      pointer-events: auto; // Override from `.mdc-dialog__container`.
      // IE 11: Otherwise, scrolling content in `mdc-dialog__content` overflows.
      overflow-y: auto;
      outline: 0;
      // Dialog scales up as it opens.
      transform: scale(0.8);

      @include rtl.rtl {
        @include rtl.ignore-next-line();
        text-align: right;
      }

      @include dom.forced-colors-mode {
        // Colored outline is used for HCM instead of transparent border
        // below to prevent scrolling content overflow.
        outline: 2px solid windowText;
      }
    }

    &::before {
      @include dom.transparent-border($border-width: 2px, $query: $query);
      @include feature-targeting.targets($feat-structure) {
        // Prevent IE11 from rendering this element, because it causes scrolling
        // content to overflow.
        @media screen and (-ms-high-contrast: active),
          screen and (-ms-high-contrast: none) {
          content: none;
        }
      }
    }
  }

  .mdc-dialog__title {
    @include typography.text-baseline(
      $top: 40px,
      $display: block,
      $lineHeight: null,
      $query: $query
    );
    @include feature-targeting.targets($feat-structure) {
      position: relative;
      flex-shrink: 0;
      box-sizing: border-box;
      margin: 0 0 1px;
      padding: 0 24px variables.$title-bottom-padding;

      @include rtl.rtl {
        @include rtl.ignore-next-line();
        text-align: right;
      }
    }
  }

  .mdc-dialog--scrollable .mdc-dialog__title {
    @include feature-targeting.targets($feat-structure) {
      margin-bottom: 1px;
      // Adjust bottom padding to make title height align to spec when divider is present.
      // (Titles for alert dialogs w/o dividers align based on text baseline. All spec values are divisible by 4.)
      padding-bottom: variables.$title-bottom-padding + 6px;
    }
  }

  .mdc-dialog--fullscreen {
    .mdc-dialog__header {
      @include feature-targeting.targets($feat-structure) {
        align-items: baseline;
        border-bottom: 1px solid transparent;
        display: inline-flex;
        justify-content: space-between;
        padding: 0 variables.$header-side-padding
          variables.$title-bottom-padding;
        z-index: 1;

        @include dom.forced-colors-mode($exclude-ie11: true) {
          border-bottom-color: CanvasText;
        }

        @include _modal-header(
          $close-icon-padding: variables.$close-icon-padding
        );
      }
    }

    .mdc-dialog__title {
      @include feature-targeting.targets($feat-structure) {
        margin-bottom: 0;
        padding: 0;
        border-bottom: 0;
      }
    }

    &.mdc-dialog--scrollable .mdc-dialog__title {
      @include feature-targeting.targets($feat-structure) {
        border-bottom: 0;
        margin-bottom: 0;
      }
    }

    .mdc-dialog__close-tooltip-wrapper {
      @include feature-targeting.targets($feat-structure) {
        top: 5px;
      }
    }

    &.mdc-dialog--scrollable .mdc-dialog__actions {
      // If full-screen dialog is scrollable, the scroll divider over the action
      // buttons (i.e. the "footer") should only be visible when the content is
      // "cut off" by the footer. To toggle this divider, we override the
      // styling set by the mdc-dialog--scrollable class, and instead rely on
      // the mdc-dialog-scroll-divider-footer class to determine when the
      // border-top should be visible.
      @include feature-targeting.targets($feat-structure) {
        border-top: 1px solid transparent;
        @include dom.forced-colors-mode($exclude-ie11: true) {
          border-top-color: CanvasText;
        }
      }
    }
  }

  // Needed so that close affordance is aligned as if there was a title.
  .mdc-dialog--fullscreen--titleless {
    .mdc-dialog__close-tooltip-wrapper {
      @include feature-targeting.targets($feat-structure) {
        margin-top: 4px;
      }
    }

    &.mdc-dialog--scrollable .mdc-dialog__close-tooltip-wrapper {
      @include feature-targeting.targets($feat-structure) {
        margin-top: 0;
      }
    }
  }

  .mdc-dialog__content {
    @include feature-targeting.targets($feat-structure) {
      flex-grow: 1;
      box-sizing: border-box;
      margin: 0;
      overflow: auto;
    }

    // The content element already has top/bottom padding, so we need to suppress margins on its first/last children.
    > :first-child {
      @include feature-targeting.targets($feat-structure) {
        margin-top: 0;
      }
    }

    // The content element already has top/bottom padding, so we need to suppress margins on its first/last children.
    > :last-child {
      @include feature-targeting.targets($feat-structure) {
        margin-bottom: 0;
      }
    }
  }

  .mdc-dialog__title + .mdc-dialog__content,
  .mdc-dialog__header + .mdc-dialog__content {
    @include feature-targeting.targets($feat-structure) {
      // Eliminate padding to bring as close to spec as possible, relying on title padding.
      // (Spec seems inconsistent RE title/body spacing on alert vs. simple variants.)
      padding-top: 0;
    }
  }

  .mdc-dialog--scrollable .mdc-dialog__title + .mdc-dialog__content {
    @include feature-targeting.targets($feat-structure) {
      // Reduce and equalize vertical paddings when scrollable dividers are present
      // (Note: this is intentionally after title + content to take precedence)
      padding-top: 8px;
      padding-bottom: 8px;
    }
  }

  .mdc-dialog__content .mdc-deprecated-list:first-child:last-child {
    @include feature-targeting.targets($feat-structure) {
      // Override default .mdc-deprecated-list padding for content consisting exclusively of a MDC List
      padding: 6px 0 0; // Top padding balances with title height
    }
  }

  .mdc-dialog--scrollable
    .mdc-dialog__content
    .mdc-deprecated-list:first-child:last-child {
    @include feature-targeting.targets($feat-structure) {
      // Override default .mdc-deprecated-list padding for content consisting exclusively of a MDC List
      padding: 0;
    }
  }

  .mdc-dialog__actions {
    @include feature-targeting.targets($feat-structure) {
      display: flex;
      position: relative;
      flex-shrink: 0;
      flex-wrap: wrap;
      align-items: center;
      justify-content: flex-end;
      box-sizing: border-box;
      min-height: 52px;
      margin: 0;
      padding: variables.$actions-padding;
      border-top: 1px solid transparent;
      @include dom.forced-colors-mode($exclude-ie11: true) {
        border-top-color: CanvasText;
      }
    }

    .mdc-dialog--stacked & {
      @include feature-targeting.targets($feat-structure) {
        flex-direction: column;
        align-items: flex-end;
      }
    }
  }

  .mdc-dialog__button {
    @include feature-targeting.targets($feat-structure) {
      @include rtl.reflexive-box(margin, left, 8px);
    }

    &:first-child {
      @include feature-targeting.targets($feat-structure) {
        @include rtl.reflexive-box(margin, left, 0);
      }
    }

    @include feature-targeting.targets($feat-structure) {
      max-width: 100%; // Prevent long text from overflowing parent element in IE 11
      @include rtl.ignore-next-line();
      text-align: right;

      @include rtl.rtl {
        @include rtl.ignore-next-line();
        text-align: left;
      }
    }

    .mdc-dialog--stacked &:not(:first-child) {
      @include feature-targeting.targets($feat-structure) {
        margin-top: 12px;
      }
    }
  }

  .mdc-dialog--open,
  .mdc-dialog--opening,
  .mdc-dialog--closing {
    @include feature-targeting.targets($feat-structure) {
      display: flex;
    }
  }

  .mdc-dialog--opening {
    .mdc-dialog__scrim {
      @include feature-targeting.targets($feat-animation) {
        transition: opacity 150ms linear;
      }
    }

    .mdc-dialog__container {
      @include feature-targeting.targets($feat-animation) {
        transition:
          opacity 75ms linear,
          animation-functions.enter(transform, 150ms);
      }
    }
  }

  .mdc-dialog--closing {
    .mdc-dialog__scrim,
    .mdc-dialog__container {
      @include feature-targeting.targets($feat-animation) {
        transition: opacity 75ms linear;
      }
    }

    .mdc-dialog__container {
      @include feature-targeting.targets($feat-structure) {
        transform: none;
      }
    }

    .mdc-dialog__surface {
      @include feature-targeting.targets($feat-structure) {
        // Dialog container scales up while opening, but should remain scaled up while closing
        transform: none;
      }
    }
  }

  // Override the above transitions when chaining dialogs.
  .mdc-dialog--chaining .mdc-dialog__scrim {
    @include feature-targeting.targets($feat-animation) {
      transition: none;
    }
    @include feature-targeting.targets($feat-structure) {
      opacity: 1;
    }
  }

  .mdc-dialog--open {
    .mdc-dialog__scrim {
      @include feature-targeting.targets($feat-structure) {
        opacity: 1;
      }
    }

    .mdc-dialog__container {
      @include feature-targeting.targets($feat-structure) {
        opacity: 1;
      }
    }

    .mdc-dialog__surface {
      @include feature-targeting.targets($feat-structure) {
        transform: none;
      }
    }

    &.mdc-dialog__surface-scrim--shown {
      .mdc-dialog__surface-scrim {
        @include feature-targeting.targets($feat-structure) {
          opacity: 1;
        }
      }
    }

    &.mdc-dialog__surface-scrim--hiding {
      .mdc-dialog__surface-scrim {
        @include feature-targeting.targets($feat-animation) {
          transition: opacity 75ms linear;
        }
      }
    }

    &.mdc-dialog__surface-scrim--showing {
      .mdc-dialog__surface-scrim {
        @include feature-targeting.targets($feat-animation) {
          transition: opacity 150ms linear;
        }
      }
    }
  }

  .mdc-dialog__surface-scrim {
    @include feature-targeting.targets($feat-structure) {
      display: none;
      opacity: 0;
      position: absolute;
      width: 100%;
      height: 100%;
      z-index: 1;
    }

    .mdc-dialog__surface-scrim--shown &,
    .mdc-dialog__surface-scrim--showing &,
    .mdc-dialog__surface-scrim--hiding & {
      @include feature-targeting.targets($feat-structure) {
        display: block;
      }
    }
  }

  // postcss-bem-linter: end

  // Class applied to body while dialog is open, to prevent scrolling behind the dialog
  .mdc-dialog-scroll-lock {
    @include feature-targeting.targets($feat-structure) {
      overflow: hidden;
    }
  }

  .mdc-dialog--no-content-padding {
    .mdc-dialog__content {
      @include feature-targeting.targets($feat-structure) {
        padding: 0;
      }
    }
  }

  .mdc-dialog--sheet {
    .mdc-dialog__container .mdc-dialog__close-tooltip-wrapper {
      @include feature-targeting.targets($feat-structure) {
        right: variables.$sheet-close-icon-right;
        top: variables.$sheet-close-icon-top;
        position: absolute;
        // Customers can create their stacking context in dialog content using
        // any way of createing stacking context. For example with
        //   position: relative;
        //   z-index: 0;
        z-index: 1;
      }
    }
  }

  .mdc-dialog__scrim--removed {
    @include feature-targeting.targets($feat-structure) {
      pointer-events: none;
    }

    .mdc-dialog__scrim,
    .mdc-dialog__surface-scrim {
      @include feature-targeting.targets($feat-structure) {
        display: none;
      }
    }
  }
}

@mixin core-styles($query: feature-targeting.all()) {
  $feat-structure: feature-targeting.create-target($query, structure);

  .mdc-dialog {
    @include container-fill-color(surface, $query: $query);
    @include scrim-color(variables.$scrim-color, $query: $query);
    @include title-ink-color(variables.$title-ink-color, $query: $query);
    @include content-ink-color(variables.$content-ink-color, $query: $query);
    @include scroll-divider-color(
      variables.$scroll-divider-color,
      $query: $query
    );
    @include shape-radius(variables.$shape-radius, $query: $query);
  }

  .mdc-dialog__surface {
    @include elevation-mixins.elevation(24, $query: $query);
  }

  .mdc-dialog__title {
    @include typography.typography(headline6, $query: $query);
  }

  .mdc-dialog__content {
    @include typography.typography(body1, $query: $query);
  }

  // For go/soy-checks/rewrite-css
  .mdc-dialog__title-icon {
    @include feature-targeting.targets($feat-structure) {
      /** Hook for theming API. */
    }
  }

  @include static-styles($query: $query);
}

@mixin container-fill-color($color, $query: feature-targeting.all()) {
  $feat-color: feature-targeting.create-target($query, color);

  .mdc-dialog__surface {
    @include feature-targeting.targets($feat-color) {
      @include theme.property(background-color, $color);
    }
  }
}

@mixin scrim-color(
  $color,
  $opacity: variables.$scrim-opacity,
  $query: feature-targeting.all()
) {
  $feat-color: feature-targeting.create-target($query, color);

  .mdc-dialog__scrim {
    @include feature-targeting.targets($feat-color) {
      background-color: rgba(theme-color.prop-value($color), $opacity);
    }
  }

  .mdc-dialog__surface-scrim {
    @include feature-targeting.targets($feat-color) {
      background-color: rgba(theme-color.prop-value($color), $opacity);
    }
  }
}

@mixin title-ink-color(
  $color,
  $opacity: variables.$title-ink-opacity,
  $query: feature-targeting.all()
) {
  $feat-color: feature-targeting.create-target($query, color);

  .mdc-dialog__title {
    @include feature-targeting.targets($feat-color) {
      color: rgba(theme-color.prop-value($color), $opacity);
    }
  }
}

@mixin content-ink-color(
  $color,
  $opacity: variables.$content-ink-opacity,
  $query: feature-targeting.all()
) {
  $feat-color: feature-targeting.create-target($query, color);

  .mdc-dialog__content {
    @include feature-targeting.targets($feat-color) {
      color: rgba(theme-color.prop-value($color), $opacity);
    }
  }

  .mdc-dialog__close {
    @include icon-button-theme.ink_color($color: $color, $query: $query);
  }
}

/// Defines the `display` property of the content element using a given query.
/// This is useful if the content of the dialog needs to use a custom layout,
/// for example one that consists of a fixed header and a fixed footer, with a
/// scrollable list area in-between, which is sized to fill available space
/// (see b/231813016).
/// @param {string} $display - The `display` type to set.
/// @param {string} $query Query.
@mixin content-display($display, $query: feature-targeting.all()) {
  $feat-structure: feature-targeting.create-target($query, structure);

  .mdc-dialog__content {
    @include feature-targeting.targets($feat-structure) {
      display: $display;
    }
  }
}

@mixin content-padding(
  $padding-top,
  $padding-right,
  $padding-bottom,
  $padding-left,
  $query: feature-targeting.all()
) {
  $feat-structure: feature-targeting.create-target($query, structure);

  .mdc-dialog__content {
    @include feature-targeting.targets($feat-structure) {
      padding: $padding-top $padding-right $padding-bottom $padding-left;
    }
  }
}

@mixin scroll-divider-color(
  $color,
  $opacity: variables.$scroll-divider-opacity,
  $query: feature-targeting.all()
) {
  $feat-color: feature-targeting.create-target($query, color);

  &.mdc-dialog--scrollable .mdc-dialog__title,
  &.mdc-dialog--scrollable .mdc-dialog__actions,
  &.mdc-dialog--scrollable.mdc-dialog-scroll-divider-footer
    .mdc-dialog__actions {
    @include feature-targeting.targets($feat-color) {
      border-color: rgba(theme-color.prop-value($color), $opacity);
    }
  }

  &.mdc-dialog--scrollable .mdc-dialog__title {
    @include feature-targeting.targets($feat-color) {
      border-bottom: 1px solid rgba(theme-color.prop-value($color), $opacity);
      margin-bottom: 0;
    }
  }

  &.mdc-dialog-scroll-divider-header.mdc-dialog--fullscreen
    .mdc-dialog__header {
    @include elevation-mixins.elevation(2, $query: $query);
  }
}

@mixin shape-radius(
  $radius,
  $rtl-reflexive: false,
  $query: feature-targeting.all()
) {
  $feat-structure: feature-targeting.create-target($query, structure);

  .mdc-dialog__surface {
    @include shape-mixins.radius($radius, $rtl-reflexive, $query: $query);
  }
}

@mixin min-width($min-width, $query: feature-targeting.all()) {
  $feat-structure: feature-targeting.create-target($query, structure);

  .mdc-dialog__surface {
    @include feature-targeting.targets($feat-structure) {
      min-width: $min-width;
    }
  }
}

@mixin min-height($min-height, $query: feature-targeting.all()) {
  $feat-structure: feature-targeting.create-target($query, structure);

  .mdc-dialog__surface {
    @include feature-targeting.targets($feat-structure) {
      min-height: $min-height;
    }
  }
}

@mixin max-width-with-breakpoint(
  $above-breakpoint-max-width,
  $below-breakpoint-max-width,
  $max-width-breakpoint,
  $query: feature-targeting.all()
) {
  $feat-structure: feature-targeting.create-target($query, structure);

  .mdc-dialog__surface {
    @include feature-targeting.targets($feat-structure) {
      @media (max-width: $max-width-breakpoint) {
        max-width: $below-breakpoint-max-width;
      }
      @media (min-width: $max-width-breakpoint) {
        max-width: $above-breakpoint-max-width;
      }
    }
  }
}

@mixin max-width($max-width, $margin, $query: feature-targeting.all()) {
  $feat-structure: feature-targeting.create-target($query, structure);
  $max-width-breakpoint: $max-width + ($margin * 2);
  // Fit snugly within the viewport at smaller screen sizes.
  $below-breakpoint-max-width: calc(100vw - #{$margin * 2});

  @if $max-width {
    @include max-width-with-breakpoint(
      $max-width,
      $below-breakpoint-max-width,
      $max-width-breakpoint,
      $query
    );
  } @else {
    .mdc-dialog__surface {
      @include feature-targeting.targets($feat-structure) {
        max-width: $below-breakpoint-max-width;
      }
    }
  }
}

@mixin max-height($max-height, $margin, $query: feature-targeting.all()) {
  $feat-structure: feature-targeting.create-target($query, structure);
  $max-size-calc-expr: calc(100% - #{$margin * 2});

  .mdc-dialog__surface {
    @include feature-targeting.targets($feat-structure) {
      @if $max-height {
        $max-height-breakpoint: $max-height + ($margin * 2);

        // Fit snugly within the viewport at smaller screen sizes.
        @media (max-height: $max-height-breakpoint) {
          max-height: $max-size-calc-expr;
        }

        // Once the screen gets big enough, apply a fixed maximum height.
        @media (min-height: $max-height-breakpoint) {
          max-height: $max-height;
        }
      } @else {
        max-height: $max-size-calc-expr;
      }
    }
  }

  // Target IE 11.
  @media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
    // On IE 11, if surface height is fixed and container height is 100%,
    // scrolling content overflows. So, reset height if surface height
    // is fixed.
    .mdc-dialog__container {
      @include feature-targeting.targets($feat-structure) {
        @if $max-height {
          $max-height-breakpoint: $max-height + ($margin * 2);

          @media (min-height: $max-height-breakpoint) {
            align-items: stretch;
            height: auto;
          }
        }
      }
    }
  }
}

// Applied to dialogs that have buttons with an increased touch target.
@mixin with-touch-target($query: feature-targeting.all()) {
  $feat-structure: feature-targeting.create-target($query, structure);
  $touch-target-margin: math.div(
    touch-target-variables.$height - button-theme.$height,
    2
  );
  $vertical-padding: math.max(
    0,
    variables.$actions-padding - $touch-target-margin
  );

  // Buttons with an increased touch target have added vertical margin, so
  // decrease the actions element padding to compensate.
  .mdc-dialog__actions {
    @include feature-targeting.targets($feat-structure) {
      padding-top: $vertical-padding;
      padding-bottom: $vertical-padding;

      // The below styles override the default button touch target values,
      // which otherwise cause `mdc-dialog__surface` to scroll unnnecessarily
      // in IE 11.
      .mdc-button__touch {
        top: -$touch-target-margin; // IE 11
        transform: none; // IE 11
      }
    }
  }
}

/// Defines dialog position on the screen.
/// Dialog position can be customised across both vertical and horizontal axis.
/// If only one axis is specified dialog is centered across the second one.
/// Only one value can be specified for each axis at the time. For example
/// dialog can not have both $top and $bottom specified because it will conflict
/// with size related mixins. Use `min-width`, `max-width` and `max-height`
/// to control the dialog size.
/// @param {Map} $position-map - Dialog position specified as map with keys
///     {top, bottom, left, right}
@mixin position($position-map, $query: feature-targeting.all()) {
  $feat-structure: feature-targeting.create-target($query, structure);
  $top: map.get($position-map, top);
  $right: map.get($position-map, right);
  $bottom: map.get($position-map, bottom);
  $left: map.get($position-map, left);

  @if ($top != null and $bottom != null) {
    @error "Top and Botton properties can not be used simultaneously. Use " +
           "`min-width`, `max-width` and `max-height` to control dialog size.";
  }
  @if ($right != null and $left != null) {
    @error "Right and Left properties can not be used simultaneously. Use " +
           "`min-width`, `max-width` and `max-height` to control dialog size.";
  }

  @include feature-targeting.targets($feat-structure) {
    @if ($top != null) {
      .mdc-dialog__container {
        align-items: flex-start;
        padding-top: $top;
      }
    }
    @if ($bottom != null) {
      .mdc-dialog__container {
        align-items: flex-end;
        padding-bottom: $bottom;
      }
    }
    @if ($right != null) {
      &.mdc-dialog {
        justify-content: flex-end;
        padding-right: $right;
      }
    }
    @if ($left != null) {
      &.mdc-dialog {
        justify-content: flex-start;
        padding-left: $left;
      }
    }
  }
}

/// Defines dialog base z-index.
/// This mixin can be used to specify dialog base z-index to make it compatible
/// with other frameworks used on the same page.
/// @param {Number} $z-index - Dialog z-index value.
@mixin z-index($z-index, $query: feature-targeting.all()) {
  $feat-structure: feature-targeting.create-target($query, structure);

  @include feature-targeting.targets($feat-structure) {
    &.mdc-dialog {
      z-index: $z-index;
    }
  }
}

/// This mixin can be used to hide the fullscreen dialog header when the dialog
/// is a standard modal and not yet fullscreen in X-small sizes.
@mixin fullscreen-dialog-hide-modal-header($query: feature-targeting.all()) {
  $feat-structure: feature-targeting.create-target($query, structure);

  // Non-fullscreen-dialog sizes
  @media (min-width: 600px) {
    &.mdc-dialog--fullscreen {
      .mdc-dialog__header {
        @include feature-targeting.targets($feat-structure) {
          display: none;
        }
      }

      .mdc-dialog__content {
        @include feature-targeting.targets($feat-structure) {
          padding-top: 24px;
        }
      }
    }
  }
}

@mixin _fullscreen-dialog-size($query: feature-targeting.all()) {
  $feat-structure: feature-targeting.create-target($query, structure);
  .mdc-dialog__surface {
    @include feature-targeting.targets($feat-structure) {
      // Reset the max-width so the default dialog sizing doesn't interfere with
      // the full-screen dialog sizing.
      max-width: none;
    }

    // Medium screens
    @media (max-width: 960px) {
      @include feature-targeting.targets($feat-structure) {
        max-height: 560px;
        width: 560px;
        @include _modal-header(
          $close-icon-padding: variables.$close-icon-padding
        );
      }
    }

    // Small screens
    @media (max-width: 720px) {
      @include feature-targeting.targets($feat-structure) {
        $max-small-height: 560px;
        $max-small-width: 560px;
        $min-horizontal-small-margin: 56px;
        $min-vertical-small-margin: 80px;
        @include _fluid-size-calc(
          $vertical-margin: $min-vertical-small-margin,
          $max-height: $max-small-height,
          $horizontal-margin: $min-horizontal-small-margin,
          $max-width: $max-small-width
        );
        @include _modal-header(
          $close-icon-padding: variables.$close-icon-padding
        );
      }
    }

    // X-Small Screens
    @media (max-width: 720px) and (max-height: 400px),
      (max-width: 600px),
      (min-width: 720px) and (max-height: 400px) {
      @include feature-targeting.targets($feat-structure) {
        // Use 100% instead of vw/vh so the url bar is taken into account on
        // mobile.
        height: 100%;
        max-height: 100vh;
        max-width: 100vw;
        width: 100vw;
        @include _fullscreen-header(
          $close-icon-padding: variables.$close-icon-padding,
          $title-side-padding: variables.$title-side-padding
        );
      }
      @include shape-mixins.radius(0, $query: $query);
    }

    // Large to X-Large screens
    @media (min-width: 960px) {
      @include feature-targeting.targets($feat-structure) {
        $min-horizontal-margin: 200px;
        width: calc(100vw - #{$min-horizontal-margin * 2});
        @include _modal-header(
          $close-icon-padding: variables.$close-icon-padding
        );
      }
    }
  }
}

/// Defines styling to specify a fluid dialog size while maintaining a specific
/// vertical and horizontal margin.
/// @param  {Number} $vertical-margin
/// @param  {Number} $max-height
/// @param  {Number} $horizontal-margin
/// @param  {Number} $max-width
@mixin _fluid-size-calc(
  $vertical-margin,
  $max-height,
  $horizontal-margin,
  $max-width
) {
  $max-width-calc-expr: calc(100vw - #{$horizontal-margin * 2});
  $max-width-breakpoint: $max-width + ($horizontal-margin * 2);

  @media (max-width: $max-width-breakpoint) {
    width: $max-width-calc-expr;
  }
  @media (min-width: $max-width-breakpoint) {
    width: $max-width;
  }

  $max-height-calc-expr: calc(100vh - #{$vertical-margin * 2});
  $max-height-breakpoint: $max-height + ($vertical-margin * 2);

  @media (max-height: $max-height-breakpoint) {
    max-height: $max-height-calc-expr;
  }
  @media (min-height: $max-height-breakpoint) {
    max-height: $max-height;
  }
}

/// Defines styles for the header bar when a dialog takes up the full screen.
/// @param  {Number} $close-icon-padding - Padding on close icon button.
/// @param  {Number} $title-side-padding - Space between the edge of the close
///   icon button and edge of the title.
@mixin _fullscreen-header($close-icon-padding, $title-side-padding) {
  .mdc-dialog__close-tooltip-wrapper {
    position: relative;
    order: -1;
    @include theme.property(left, -#{$close-icon-padding});
  }
  .mdc-dialog__header {
    padding: 0 variables.$fullscreen-header-side-padding
      variables.$title-bottom-padding;
    justify-content: flex-start;
  }
  .mdc-dialog__title {
    @include theme.property(
      margin-left,
      'calc(title - 2 * close)',
      $replace: (title: $title-side-padding, close: $close-icon-padding)
    );
  }
}

/// Defines styles for the header bar when a dialog is modal.
/// @param  {Number} $close-icon-padding - Padding on close icon button.
@mixin _modal-header($close-icon-padding) {
  .mdc-dialog__close-tooltip-wrapper {
    position: relative;
    @include theme.property(right, -#{$close-icon-padding});
  }
}
